package org.goodsl.mdd

/**
 * Created with IntelliJ IDEA.
 * User: 萧猛
 * Date: 12-10-27
 * Time: 下午5:33
 * To change this template use File | Settings | File Templates.
 */
public class Seg implements Comparable<Object> {

    private static final String TYPE_VALUE = "value";

    public ValidResult verify() {
        return  segInfo.verify(this)
    }

    public Object propertyMissing(String dependAspectName) {

        if (_forParse) {
            DependAspectInfo aspectInfo = inTheBox.boxInfo.getDependAspectInfo(dependAspectName)
            if (aspectInfo == null) return
            Class valueType = aspectInfo.aspectNote.value()
            return BoxBuilder.getTypeDefaultValue(valueType)
        }
        Object newValue = allValues.get(dependAspectName);
        if (newValue == null)
            newValue = update(dependAspectName)
        return newValue
    }

    public Object propertyMissing(String dependAspectName, Object value) {
        return innerSetValue(dependAspectName, value)
    }

    private Object innerSetValue(String aspectName, Object value) {
        MetaClass mc
        Object newValue = value
        Object oldValue = allValues[aspectName]

        try {
            //这里不处理类型转换，留待后面赋值的时后处理
            if (newValue == oldValue) return newValue
        } catch (ClassCastException e) {}

        //获取值类型
        Class valueType
        Class typeConvertor
        if (TYPE_VALUE.equals(aspectName)) {
            valueType = segInBox.segInfo.valueType
            typeConvertor = segInBox.segInfo.typeConvertor
            mc = this.metaClass
        } else {
            DependAspectInfo aspectInfo = inTheBox.boxInfo.getDependAspectInfo(aspectName)
            if (aspectInfo == null) return
            valueType = aspectInfo.aspectNote.value()
            typeConvertor = aspectInfo.aspectNote.typeConvertor()
            mc = inTheBox.metaClass
        }
        if (valueType.isPrimitive())  //将原生类型转为对象类型
            valueType = SegInfo.getAutoBoxedType(valueType)
        //进行类型检查

        if (value.class != valueType) {
            //类型转换。优先使用类型自身定义的转换器，
            //如果没有就使用标注中定义的转换器，标注中未指定会用缺省转换器 DefaultTypeTransformation
            Class[] paramTypes = [Object, Class]

            MetaMethod mm = mc.pickMethod("castToType", paramTypes)
            if (mm == null) {
                if (typeConvertor != null)
                    mm = typeConvertor.metaClass.pickMethod("castToType", paramTypes)
            }
            if (mm != null)
                newValue = mm.invoke(this, value, valueType)
        }
        allValues.put(aspectName, newValue);
        inTheBox.updateAllDependOn(segInBox.segName)
        return newValue
    }

    private Class valueType;

    private void setValueType(Class cz) {}

    public Class getValueType() {
        if (valueType == null) {
            valueType = segInBox.segInfo.valueType
        }
        return valueType
    }

    private boolean _forParse = false

    protected void setForParse(boolean forParse) {
        this._forParse = forParse
    }

    Box inTheBox

    protected void setInTheBox(Box box) {
        inTheBox = box
    }

    SegInBox segInBox
    protected void setSegInBox(SegInBox segInBox) {
        this.segInBox = segInBox
    }
    SegInfo segInfo
    protected void setSegInfo(SegInfo segInfo){
        this.segInfo = segInfo
    }


    public Object getValue() {
        if (_forParse)
            return BoxBuilder.getTypeDefaultValue(getValueType())
        return allValues.get("value");
    }

    public void setValue(Object value) {
        innerSetValue(TYPE_VALUE, value)

    }

    /**
     * 更新某一个属性的值，一般这个属性应该是某个Box中的依赖属性
     * @param dependAspectName
     * @return
     */
    public Object update(String dependAspectName) {
        Object newValue = inTheBox.calcSegValue(segInBox.segName, dependAspectName)
        return innerSetValue(dependAspectName, newValue)

    }

    private HashMap<String, Object> allValues = new HashMap<String, Object>(4)



    int compareTo(Object other) {
        if (Seg.isAssignableFrom(other.class)) {
            Seg theOther = (Seg) other
            int result = this.value.compareTo(theOther.value)
            return result
        }
        Class valueType = this.getValueType()
        if (valueType == other.class) {
            int result = this.value.compareTo(other)
            return result
        }
        Object transedValue = other
        //类型转换。优先使用类型自身定义的转换器，
        //如果没有就使用标注中定义的转换器，标注中未指定会用缺省转换器 DefaultTypeTransformation
        Class[] paramTypes = [Object, Class]

        MetaMethod mm = this.metaClass.pickMethod("castToType", paramTypes)
        if (mm == null) {
            Class typeConvertor = segInBox.segInfo.typeConvertor
            if (typeConvertor != null)
                mm = typeConvertor.metaClass.pickMethod("castToType", paramTypes)
        }
        if (mm != null)
            transedValue = mm.invoke(this, other, valueType)

        return this.value.compareTo(transedValue)
    }

}
